all files / fc-er/ ajax.js

83.44% Statements 131/157
77.63% Branches 59/76
47.62% Functions 10/21
83.44% Lines 131/157
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391                  12× 12×       74× 13× 13×     74×   74× 74×   74× 74×     29× 29× 24× 24× 24×   29×   41×       24×                                   23×                   23×                         19×     19× 19×   19×             19× 19×   19× 19×   19×       18×   18×   18× 18×                                           18×   18× 18×                                       18× 50× 16×   16×       16× 16× 16× 16×   16×       16×     14× 14×           12×           11×       18×   18× 18× 18×   18× 16×   18× 18× 18× 14× 14×     18×   18×     18×   11× 11× 11×     11× 11×     18×                           18×                                                                                                                                                                                          
/**
 * ER (Enterprise RIA)
 * Copyright 2013 Baidu Inc. All rights reserved.
 *
 * @ignore
 * @file AJAX相关方法
 * @author otakustay
 */
define(function (require) {
    var TIMESTAMP_PARAM_KEY = '_';
 
    function serializeArray(prefix, array) {
        var encodedKey = prefix ? encodeURIComponent(prefix) : '';
        var encoded = [];
        for (var i = 0; i < array.length; i++) {
            var item = array[i];
            encoded[i] = this.serializeData('', item);
        }
        return encodedKey ? encodedKey + '=' + encoded.join(',') : encoded.join(',');
    }
 
    function serializeData(prefix, data) {
        if (arguments.length === 1) {
            data = prefix;
            prefix = '';
        }
 
        if (data == null) {
            data = '';
        }
        var getKey = this.serializeData.getKey;
        var encodedKey = prefix ? encodeURIComponent(prefix) : '';
 
        var type = Object.prototype.toString.call(data);
        switch (type) {
            case '[object Array]':
                return this.serializeArray(prefix, data);
            case '[object Object]':
                var result = [];
                for (var name in data) {
                    var propertyKey = getKey(name, prefix);
                    var propertyValue = this.serializeData(propertyKey, data[name]);
                    result.push(propertyValue);
                }
                return result.join('&');
            default:
                return encodedKey ? encodedKey + '=' + encodeURIComponent(data) : encodeURIComponent(data);
        }
    }
 
    serializeData.getKey = function (propertyName, parentKey) {
        return parentKey ? parentKey + '.' + propertyName : propertyName;
    };
 
    /**
     * @class Ajax
     *
     * Ajax类
     *
     * 通过`require('er/ajax').Ajax`访问该类构造函数,其中`require('er/ajax')`是该类的全局实例
     *
     * @extends mini-event.EventTarget
     * @constructor
     */
    var exports = {};
    exports.constructor = function () {
        /**
         * AJAX钩子
         *
         * @type {meta.AjaxHook}
         */
        this.hooks = {
            serializeData: serializeData,
            serializeArray: serializeArray
        };
 
        /**
         * AJAX配置
         *
         * @type {meta.AjaxOption}
         */
        this.config = {
            cache: false,
            timeout: 0,
            charset: ''
        };
    };
 
    /**
     * 发起`XMLHttpRequest`请求
     *
     * @param {meta.AjaxOption} options 相关配置
     * @return {meta.FakeXHR}
     */
    exports.request = function (options) {
        if (typeof this.hooks.beforeExecute === 'function') {
            this.hooks.beforeExecute(options);
        }
 
        var assert = require('./assert');
        assert.hasProperty(options, 'url', 'url property is required');
 
        var defaults = {
            method: 'POST',
            data: {},
            cache: this.config.cache,
            timeout: this.config.timeout,
            charset: this.config.charset
        };
        var util = require('./util');
        options = util.mix(defaults, options);
 
        var Deferred = require('./Deferred');
        var requesting = new Deferred();
 
        if (typeof this.hooks.beforeCreate === 'function') {
            var canceled = this.hooks.beforeCreate(options, requesting);
            if (canceled === true) {
                var fakeXHR = requesting.promise;
                fakeXHR.abort = function () {};
                fakeXHR.setRequestHeader = function () {};
                return fakeXHR;
            }
        }
 
        var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new window.ActiveXObject('Microsoft.XMLHTTP');
 
        util.mix(xhr, options.xhrFields);
 
        var fakeXHR = requesting.promise;
        var xhrWrapper = {
            abort: function abort() {
                // 有些浏览器`abort()`就会把`readyState`变成4,
                // 这就会导致进入处理函数变成**resolved**状态,
                // 因此事先去掉处理函数,然后直接进入**rejected**状态
                xhr.onreadystatechange = null;
                try {
                    xhr.abort();
                } catch (ex) {}
                Iif (!fakeXHR.status) {
                    fakeXHR.status = 0;
                }
                fakeXHR.readyState = xhr.readyState;
                fakeXHR.responseText = '';
                fakeXHR.responseXML = '';
                requesting.reject(fakeXHR);
            },
            setRequestHeader: function setRequestHeader(name, value) {
                xhr.setRequestHeader(name, value);
            },
            getAllResponseHeaders: function getAllResponseHeaders() {
                return xhr.getAllResponseHeaders();
            },
            getResponseHeader: function getResponseHeader(name) {
                return xhr.getResponseHeader(name);
            },
            getRequestOption: function getRequestOption(name) {
                return options[name];
            }
        };
        util.mix(fakeXHR, xhrWrapper);
 
        var eventObject = { xhr: fakeXHR, options: options };
        fakeXHR.then(
        /**
         * @event done
         *
         * 任意一个请求成功时触发
         *
         * @param {meta.AjaxOption} options 请求的配置信息
         * @param {meta.FakeXHR} xhr 请求对象
         */
        util.bind(this.fire, this, 'done', eventObject),
        /**
         * @event fail
         *
         * 任意一个请求失败时触发
         *
         * @param {meta.FakeXHR} xhr 请求对象
         * @param {meta.AjaxOption} options 请求的配置信息
         */
        util.bind(this.fire, this, 'fail', eventObject));
 
        var processRequestStatus = function processRequestStatus() {
            if (xhr.readyState === 4) {
                var status = fakeXHR.status || xhr.status;
                // IE9会把204状态码变成1223
                Iif (status === 1223) {
                    status = 204;
                }
 
                fakeXHR.status = fakeXHR.status || status;
                fakeXHR.readyState = xhr.readyState;
                fakeXHR.responseText = xhr.responseText;
                fakeXHR.responseXML = xhr.responseXML;
 
                if (typeof this.hooks.afterReceive === 'function') {
                    this.hooks.afterReceive(fakeXHR, options);
                }
 
                // 如果请求不成功,也就不用再分解数据了,直接丢回去就好
                if (status < 200 || status >= 300 && status !== 304) {
                    requesting.reject(fakeXHR);
                    return;
                }
 
                var data = xhr.responseText;
                if (options.dataType === 'json') {
                    try {
                        data = util.parseJSON(data);
                    } catch (ex) {
                        // 服务器返回的数据不符合JSON格式,认为请求失败
                        fakeXHR.error = ex;
                        requesting.reject(fakeXHR);
                        return;
                    }
                }
 
                if (typeof this.hooks.afterParse === 'function') {
                    try {
                        data = this.hooks.afterParse(data, fakeXHR, options);
                    } catch (ex) {
                        fakeXHR.error = ex;
                        requesting.reject(fakeXHR);
                        return;
                    }
                }
 
                // 数据处理成功后,进行回调
                requesting.resolve(data);
            }
        };
 
        xhr.onreadystatechange = util.bind(processRequestStatus, this);
 
        var method = options.method.toUpperCase();
        var data = {};
        if (method === 'GET') {
            util.mix(data, options.data);
        }
        if (options.cache === false) {
            data[TIMESTAMP_PARAM_KEY] = +new Date();
        }
        var query = this.hooks.serializeData('', data, 'application/x-www-form-urlencoded');
        var url = options.url;
        if (query) {
            var delimiter = url.indexOf('?') >= 0 ? '&' : '?';
            url += delimiter + query;
        }
 
        xhr.open(method, url, true);
 
        if (typeof this.hooks.beforeSend === 'function') {
            this.hooks.beforeSend(fakeXHR, options);
        }
 
        if (method === 'GET') {
            xhr.send();
        } else {
            var contentType = options.contentType || 'application/x-www-form-urlencoded';
            var query = this.hooks.serializeData('', options.data, contentType, fakeXHR);
            Iif (options.charset) {
                contentType += ';charset=' + options.charset;
            }
            xhr.setRequestHeader('Content-Type', contentType);
            xhr.send(query);
        }
 
        if (options.timeout > 0) {
            var notifyTimeout = function notifyTimeout() {
                /**
                 * @event timeout
                 *
                 * 任意一个请求成功时触发,
                 * 在此事件后会再触发一次{@link Ajax#fail}事件
                 *
                 * @param {meta.FakeXHR} xhr 请求对象
                 * @param {meta.AjaxOption} options 请求的配置信息
                 */
                this.fire('timeout', { xhr: fakeXHR, options: options });
                fakeXHR.status = 408; // HTTP 408: Request Timeout
                fakeXHR.abort();
            };
            var tick = setTimeout(util.bind(notifyTimeout, this), options.timeout);
            fakeXHR.ensure(function () {
                clearTimeout(tick);
            });
        }
 
        return fakeXHR;
    };
 
    /**
     * 发起一个`GET`请求
     *
     * @param {string} url 请求的地址
     * @param {Object} [data] 请求的数据
     * @param {boolean} [cache] 决定是否允许缓存
     * @return {meta.FakeXHR}
     */
    exports.get = function (url, data, cache) {
        var options = {
            method: 'GET',
            url: url,
            data: data,
            cache: cache || this.config.cache
        };
        return this.request(options);
    };
 
    /**
     * 发起一个`GET`请求并获取JSON数据
     *
     * @param {string} url 请求的地址
     * @param {Object} [data] 请求的数据
     * @param {boolean} [cache] 决定是否允许缓存
     * @return {meta.FakeXHR}
     */
    exports.getJSON = function (url, data, cache) {
        var options = {
            method: 'GET',
            url: url,
            data: data,
            dataType: 'json',
            cache: cache || this.config.cache
        };
        return this.request(options);
    };
 
    /**
     * 发起一个`POST`请求
     *
     * @param {string} url 请求的地址
     * @param {Object} [data] 请求的数据
     * @param {string} [dataType="json"] 指定响应的数据格式
     * @return {meta.FakeXHR}
     */
    exports.post = function (url, data, dataType) {
        var options = {
            method: 'POST',
            url: url,
            data: data,
            dataType: dataType || 'json'
        };
        return this.request(options);
    };
 
    /**
     * 发送一个日志请求,该请求只负责发出,不负责保证送达,且不支持回调函数
     *
     * @param {string} url 发送的目标URL
     * @param {Object} [data] 额外添加的参数
     */
    exports.log = function (url, data) {
        var img = new Image();
        var pool = window.ER_LOG_POOL || (window.ER_LOG_POOL = {});
        var id = +new Date();
        pool[id] = img;
 
        img.onload = img.onerror = img.onabort = function () {
            // 如果这个img很不幸正好加载了一个存在的资源,又是个gif动画,
            // 则在gif动画播放过程中,img会多次触发onload,因此一定要清空
            img.onload = img.onerror = img.onabort = null;
 
            pool[id] = null;
 
            // 下面这句非常重要,
            // new Image创建的是DOM,
            // DOM的事件中形成闭包环引用DOM是典型的内存泄露,
            // 因此这里一定要置为null
            img = null;
        };
 
        var query = this.hooks.serializeData('', data, 'application/x-www-form-urlencoded');
        if (query) {
            var delimiter = url.indexOf('?') >= 0 ? ':' : '?';
            url += delimiter + query;
        }
        // 一定要在注册了事件之后再设置src,
        // 不然如果图片是读缓存的话,会错过事件处理,
        // 最后,对于url最好是添加客户端时间来防止缓存,
        // 同时服务器也配合一下传递`Cache-Control: no-cache;`
        img.src = url;
    };
 
    var Ajax = require('eoo').create(require('fc-mini-event/EventTarget'), exports);
    var instance = new Ajax();
    instance.Ajax = Ajax;
    return instance;
});
//# sourceMappingURL=data:application/json;base64,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QixZQUFJLE9BQU8sT0FBTyxXQUFQLEtBQXVCLE9BQU8sV0FBUCxHQUFxQixFQUFyQixDQUF2QixDQUZvQjtBQUcvQixZQUFJLEtBQUssQ0FBQyxJQUFJLElBQUosRUFBRCxDQUhzQjtBQUkvQixhQUFLLEVBQUwsSUFBVyxHQUFYLENBSitCOztBQU0vQixZQUFJLE1BQUosR0FBYSxJQUFJLE9BQUosR0FBYyxJQUFJLE9BQUosR0FBYyxZQUFZOzs7QUFHakQsZ0JBQUksTUFBSixHQUFhLElBQUksT0FBSixHQUFjLElBQUksT0FBSixHQUFjLElBQWQsQ0FIc0I7O0FBS2pELGlCQUFLLEVBQUwsSUFBVyxJQUFYOzs7Ozs7QUFMaUQsZUFXakQsR0FBTSxJQUFOLENBWGlEO1NBQVosQ0FOVjs7QUFvQi9CLFlBQUksUUFBUSxLQUFLLEtBQUwsQ0FBVyxhQUFYLENBQXlCLEVBQXpCLEVBQTZCLElBQTdCLEVBQW1DLG1DQUFuQyxDQUFSLENBcEIyQjtBQXFCL0IsWUFBSSxLQUFKLEVBQVc7QUFDUCxnQkFBSSxZQUFZLElBQUksT0FBSixDQUFZLEdBQVosS0FBb0IsQ0FBcEIsR0FBd0IsR0FBeEIsR0FBOEIsR0FBOUIsQ0FEVDtBQUVQLG1CQUFPLFlBQVksS0FBWixDQUZBO1NBQVg7Ozs7O0FBckIrQixXQTZCL0IsQ0FBSSxHQUFKLEdBQVUsR0FBVixDQTdCK0I7S0FBckIsQ0F2V0M7O0FBdVlmLFFBQUksT0FBTyxRQUFRLEtBQVIsRUFBZSxNQUFmLENBQXNCLFFBQVEsMkJBQVIsQ0FBdEIsRUFBNEQsT0FBNUQsQ0FBUCxDQXZZVztBQXdZZixRQUFJLFdBQVcsSUFBSSxJQUFKLEVBQVgsQ0F4WVc7QUF5WWYsYUFBUyxJQUFULEdBQWdCLElBQWhCLENBelllO0FBMFlmLFdBQU8sUUFBUCxDQTFZZTtDQUFuQixDQURKIiwiZmlsZSI6ImFqYXguanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEVSIChFbnRlcnByaXNlIFJJQSlcbiAqIENvcHlyaWdodCAyMDEzIEJhaWR1IEluYy4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqXG4gKiBAaWdub3JlXG4gKiBAZmlsZSBBSkFY55u45YWz5pa55rOVXG4gKiBAYXV0aG9yIG90YWt1c3RheVxuICovXG5kZWZpbmUoXG4gICAgZnVuY3Rpb24gKHJlcXVpcmUpIHtcbiAgICAgICAgdmFyIFRJTUVTVEFNUF9QQVJBTV9LRVkgPSAnXyc7XG5cbiAgICAgICAgZnVuY3Rpb24gc2VyaWFsaXplQXJyYXkocHJlZml4LCBhcnJheSkge1xuICAgICAgICAgICAgdmFyIGVuY29kZWRLZXkgPSBwcmVmaXggPyBlbmNvZGVVUklDb21wb25lbnQocHJlZml4KSA6ICcnO1xuICAgICAgICAgICAgdmFyIGVuY29kZWQgPSBbXTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJyYXkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgaXRlbSA9IGFycmF5W2ldO1xuICAgICAgICAgICAgICAgIGVuY29kZWRbaV0gPSB0aGlzLnNlcmlhbGl6ZURhdGEoJycsIGl0ZW0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGVuY29kZWRLZXlcbiAgICAgICAgICAgICAgICA/IGVuY29kZWRLZXkgKyAnPScgKyBlbmNvZGVkLmpvaW4oJywnKVxuICAgICAgICAgICAgICAgIDogZW5jb2RlZC5qb2luKCcsJyk7XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBzZXJpYWxpemVEYXRhKHByZWZpeCwgZGF0YSkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgICAgICBkYXRhID0gcHJlZml4O1xuICAgICAgICAgICAgICAgIHByZWZpeCA9ICcnO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoZGF0YSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgZGF0YSA9ICcnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGdldEtleSA9IHRoaXMuc2VyaWFsaXplRGF0YS5nZXRLZXk7XG4gICAgICAgICAgICB2YXIgZW5jb2RlZEtleSA9IHByZWZpeCA/IGVuY29kZVVSSUNvbXBvbmVudChwcmVmaXgpIDogJyc7XG5cbiAgICAgICAgICAgIHZhciB0eXBlID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGRhdGEpO1xuICAgICAgICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAnW29iamVjdCBBcnJheV0nOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5zZXJpYWxpemVBcnJheShwcmVmaXgsIGRhdGEpO1xuICAgICAgICAgICAgICAgIGNhc2UgJ1tvYmplY3QgT2JqZWN0XSc6XG4gICAgICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgbmFtZSBpbiBkYXRhKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcGVydHlLZXkgPSBnZXRLZXkobmFtZSwgcHJlZml4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wZXJ0eVZhbHVlID0gdGhpcy5zZXJpYWxpemVEYXRhKHByb3BlcnR5S2V5LCBkYXRhW25hbWVdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKHByb3BlcnR5VmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQuam9pbignJicpO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBlbmNvZGVkS2V5XG4gICAgICAgICAgICAgICAgICAgICAgICA/IGVuY29kZWRLZXkgKyAnPScgKyBlbmNvZGVVUklDb21wb25lbnQoZGF0YSlcbiAgICAgICAgICAgICAgICAgICAgICAgIDogZW5jb2RlVVJJQ29tcG9uZW50KGRhdGEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgc2VyaWFsaXplRGF0YS5nZXRLZXkgPSBmdW5jdGlvbiAocHJvcGVydHlOYW1lLCBwYXJlbnRLZXkpIHtcbiAgICAgICAgICAgIHJldHVybiBwYXJlbnRLZXkgPyBwYXJlbnRLZXkgKyAnLicgKyBwcm9wZXJ0eU5hbWUgOiBwcm9wZXJ0eU5hbWU7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBjbGFzcyBBamF4XG4gICAgICAgICAqXG4gICAgICAgICAqIEFqYXjnsbtcbiAgICAgICAgICpcbiAgICAgICAgICog6YCa6L+HYHJlcXVpcmUoJ2VyL2FqYXgnKS5BamF4YOiuv+mXruivpeexu+aehOmAoOWHveaVsO+8jOWFtuS4rWByZXF1aXJlKCdlci9hamF4Jylg5piv6K+l57G755qE5YWo5bGA5a6e5L6LXG4gICAgICAgICAqXG4gICAgICAgICAqIEBleHRlbmRzIG1pbmktZXZlbnQuRXZlbnRUYXJnZXRcbiAgICAgICAgICogQGNvbnN0cnVjdG9yXG4gICAgICAgICAqL1xuICAgICAgICB2YXIgZXhwb3J0cyA9IHt9O1xuICAgICAgICBleHBvcnRzLmNvbnN0cnVjdG9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBBSkFY6ZKp5a2QXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogQHR5cGUge21ldGEuQWpheEhvb2t9XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHRoaXMuaG9va3MgPSB7XG4gICAgICAgICAgICAgICAgc2VyaWFsaXplRGF0YTogc2VyaWFsaXplRGF0YSxcbiAgICAgICAgICAgICAgICBzZXJpYWxpemVBcnJheTogc2VyaWFsaXplQXJyYXlcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQUpBWOmFjee9rlxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIEB0eXBlIHttZXRhLkFqYXhPcHRpb259XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHRoaXMuY29uZmlnID0ge1xuICAgICAgICAgICAgICAgIGNhY2hlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICB0aW1lb3V0OiAwLFxuICAgICAgICAgICAgICAgIGNoYXJzZXQ6ICcnXG4gICAgICAgICAgICB9O1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiDlj5HotbdgWE1MSHR0cFJlcXVlc3Rg6K+35rGCXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSB7bWV0YS5BamF4T3B0aW9ufSBvcHRpb25zIOebuOWFs+mFjee9rlxuICAgICAgICAgKiBAcmV0dXJuIHttZXRhLkZha2VYSFJ9XG4gICAgICAgICAqL1xuICAgICAgICBleHBvcnRzLnJlcXVlc3QgPSBmdW5jdGlvbiAob3B0aW9ucykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLmhvb2tzLmJlZm9yZUV4ZWN1dGUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhvb2tzLmJlZm9yZUV4ZWN1dGUob3B0aW9ucyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBhc3NlcnQgPSByZXF1aXJlKCcuL2Fzc2VydCcpO1xuICAgICAgICAgICAgYXNzZXJ0Lmhhc1Byb3BlcnR5KG9wdGlvbnMsICd1cmwnLCAndXJsIHByb3BlcnR5IGlzIHJlcXVpcmVkJyk7XG5cbiAgICAgICAgICAgIHZhciBkZWZhdWx0cyA9IHtcbiAgICAgICAgICAgICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgICAgICAgICAgICBkYXRhOiB7fSxcbiAgICAgICAgICAgICAgICBjYWNoZTogdGhpcy5jb25maWcuY2FjaGUsXG4gICAgICAgICAgICAgICAgdGltZW91dDogdGhpcy5jb25maWcudGltZW91dCxcbiAgICAgICAgICAgICAgICBjaGFyc2V0OiB0aGlzLmNvbmZpZy5jaGFyc2V0XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdmFyIHV0aWwgPSByZXF1aXJlKCcuL3V0aWwnKTtcbiAgICAgICAgICAgIG9wdGlvbnMgPSB1dGlsLm1peChkZWZhdWx0cywgb3B0aW9ucyk7XG5cbiAgICAgICAgICAgIHZhciBEZWZlcnJlZCA9IHJlcXVpcmUoJy4vRGVmZXJyZWQnKTtcbiAgICAgICAgICAgIHZhciByZXF1ZXN0aW5nID0gbmV3IERlZmVycmVkKCk7XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5ob29rcy5iZWZvcmVDcmVhdGUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICB2YXIgY2FuY2VsZWQgPSB0aGlzLmhvb2tzLmJlZm9yZUNyZWF0ZShvcHRpb25zLCByZXF1ZXN0aW5nKTtcbiAgICAgICAgICAgICAgICBpZiAoY2FuY2VsZWQgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGZha2VYSFIgPSByZXF1ZXN0aW5nLnByb21pc2U7XG4gICAgICAgICAgICAgICAgICAgIGZha2VYSFIuYWJvcnQgPSBmdW5jdGlvbiAoKSB7fTtcbiAgICAgICAgICAgICAgICAgICAgZmFrZVhIUi5zZXRSZXF1ZXN0SGVhZGVyID0gZnVuY3Rpb24gKCkge307XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWtlWEhSO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIHhociA9IHdpbmRvdy5YTUxIdHRwUmVxdWVzdFxuICAgICAgICAgICAgICAgID8gbmV3IFhNTEh0dHBSZXF1ZXN0KClcbiAgICAgICAgICAgICAgICA6IG5ldyB3aW5kb3cuQWN0aXZlWE9iamVjdCgnTWljcm9zb2Z0LlhNTEhUVFAnKTtcblxuICAgICAgICAgICAgdXRpbC5taXgoeGhyLCBvcHRpb25zLnhockZpZWxkcyk7XG5cbiAgICAgICAgICAgIHZhciBmYWtlWEhSID0gcmVxdWVzdGluZy5wcm9taXNlO1xuICAgICAgICAgICAgdmFyIHhocldyYXBwZXIgPSB7XG4gICAgICAgICAgICAgICAgYWJvcnQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8g5pyJ5Lqb5rWP6KeI5ZmoYGFib3J0KClg5bCx5Lya5oqKYHJlYWR5U3RhdGVg5Y+Y5oiQNO+8jFxuICAgICAgICAgICAgICAgICAgICAvLyDov5nlsLHkvJrlr7zoh7Tov5vlhaXlpITnkIblh73mlbDlj5jmiJAqKnJlc29sdmVkKirnirbmgIHvvIxcbiAgICAgICAgICAgICAgICAgICAgLy8g5Zug5q2k5LqL5YWI5Y675o6J5aSE55CG5Ye95pWw77yM54S25ZCO55u05o6l6L+b5YWlKipyZWplY3RlZCoq54q25oCBXG4gICAgICAgICAgICAgICAgICAgIHhoci5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgeGhyLmFib3J0KCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY2F0Y2ggKGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFmYWtlWEhSLnN0YXR1cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZmFrZVhIUi5zdGF0dXMgPSAwO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGZha2VYSFIucmVhZHlTdGF0ZSA9IHhoci5yZWFkeVN0YXRlO1xuICAgICAgICAgICAgICAgICAgICBmYWtlWEhSLnJlc3BvbnNlVGV4dCA9ICcnO1xuICAgICAgICAgICAgICAgICAgICBmYWtlWEhSLnJlc3BvbnNlWE1MID0gJyc7XG4gICAgICAgICAgICAgICAgICAgIHJlcXVlc3RpbmcucmVqZWN0KGZha2VYSFIpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgc2V0UmVxdWVzdEhlYWRlcjogZnVuY3Rpb24gKG5hbWUsIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHhoci5zZXRSZXF1ZXN0SGVhZGVyKG5hbWUsIHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGdldEFsbFJlc3BvbnNlSGVhZGVyczogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4geGhyLmdldEFsbFJlc3BvbnNlSGVhZGVycygpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZ2V0UmVzcG9uc2VIZWFkZXI6IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB4aHIuZ2V0UmVzcG9uc2VIZWFkZXIobmFtZSk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBnZXRSZXF1ZXN0T3B0aW9uOiBmdW5jdGlvbiAobmFtZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3B0aW9uc1tuYW1lXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdXRpbC5taXgoZmFrZVhIUiwgeGhyV3JhcHBlcik7XG5cbiAgICAgICAgICAgIHZhciBldmVudE9iamVjdCA9IHsgeGhyOiBmYWtlWEhSLCBvcHRpb25zOiBvcHRpb25zIH07XG4gICAgICAgICAgICBmYWtlWEhSLnRoZW4oXG4gICAgICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgICAgICogQGV2ZW50IGRvbmVcbiAgICAgICAgICAgICAgICAgKlxuICAgICAgICAgICAgICAgICAqIOS7u+aEj+S4gOS4quivt+axguaIkOWKn+aXtuinpuWPkVxuICAgICAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgICAgICogQHBhcmFtIHttZXRhLkFqYXhPcHRpb259IG9wdGlvbnMg6K+35rGC55qE6YWN572u5L+h5oGvXG4gICAgICAgICAgICAgICAgICogQHBhcmFtIHttZXRhLkZha2VYSFJ9IHhociDor7fmsYLlr7nosaFcbiAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICB1dGlsLmJpbmQodGhpcy5maXJlLCB0aGlzLCAnZG9uZScsIGV2ZW50T2JqZWN0KSxcbiAgICAgICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAgICAgKiBAZXZlbnQgZmFpbFxuICAgICAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgICAgICog5Lu75oSP5LiA5Liq6K+35rGC5aSx6LSl5pe26Kem5Y+RXG4gICAgICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAgICAgKiBAcGFyYW0ge21ldGEuRmFrZVhIUn0geGhyIOivt+axguWvueixoVxuICAgICAgICAgICAgICAgICAqIEBwYXJhbSB7bWV0YS5BamF4T3B0aW9ufSBvcHRpb25zIOivt+axgueahOmFjee9ruS/oeaBr1xuICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgIHV0aWwuYmluZCh0aGlzLmZpcmUsIHRoaXMsICdmYWlsJywgZXZlbnRPYmplY3QpXG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICB2YXIgcHJvY2Vzc1JlcXVlc3RTdGF0dXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKHhoci5yZWFkeVN0YXRlID09PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBzdGF0dXMgPSBmYWtlWEhSLnN0YXR1cyB8fCB4aHIuc3RhdHVzO1xuICAgICAgICAgICAgICAgICAgICAvLyBJRTnkvJrmiooyMDTnirbmgIHnoIHlj5jmiJAxMjIzXG4gICAgICAgICAgICAgICAgICAgIGlmIChzdGF0dXMgPT09IDEyMjMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXR1cyA9IDIwNDtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGZha2VYSFIuc3RhdHVzID0gZmFrZVhIUi5zdGF0dXMgfHwgc3RhdHVzO1xuICAgICAgICAgICAgICAgICAgICBmYWtlWEhSLnJlYWR5U3RhdGUgPSB4aHIucmVhZHlTdGF0ZTtcbiAgICAgICAgICAgICAgICAgICAgZmFrZVhIUi5yZXNwb25zZVRleHQgPSB4aHIucmVzcG9uc2VUZXh0O1xuICAgICAgICAgICAgICAgICAgICBmYWtlWEhSLnJlc3BvbnNlWE1MID0geGhyLnJlc3BvbnNlWE1MO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5ob29rcy5hZnRlclJlY2VpdmUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaG9va3MuYWZ0ZXJSZWNlaXZlKGZha2VYSFIsIG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgLy8g5aaC5p6c6K+35rGC5LiN5oiQ5Yqf77yM5Lmf5bCx5LiN55So5YaN5YiG6Kej5pWw5o2u5LqG77yM55u05o6l5Lii5Zue5Y675bCx5aW9XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdGF0dXMgPCAyMDAgfHwgKHN0YXR1cyA+PSAzMDAgJiYgc3RhdHVzICE9PSAzMDQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXF1ZXN0aW5nLnJlamVjdChmYWtlWEhSKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciBkYXRhID0geGhyLnJlc3BvbnNlVGV4dDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuZGF0YVR5cGUgPT09ICdqc29uJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gdXRpbC5wYXJzZUpTT04oZGF0YSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXRjaCAoZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyDmnI3liqHlmajov5Tlm57nmoTmlbDmja7kuI3nrKblkIhKU09O5qC85byP77yM6K6k5Li66K+35rGC5aSx6LSlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFrZVhIUi5lcnJvciA9IGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcXVlc3RpbmcucmVqZWN0KGZha2VYSFIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5ob29rcy5hZnRlclBhcnNlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSB0aGlzLmhvb2tzLmFmdGVyUGFyc2UoZGF0YSwgZmFrZVhIUiwgb3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXRjaCAoZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWtlWEhSLmVycm9yID0gZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWVzdGluZy5yZWplY3QoZmFrZVhIUik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgLy8g5pWw5o2u5aSE55CG5oiQ5Yqf5ZCO77yM6L+b6KGM5Zue6LCDXG4gICAgICAgICAgICAgICAgICAgIHJlcXVlc3RpbmcucmVzb2x2ZShkYXRhKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB4aHIub25yZWFkeXN0YXRlY2hhbmdlID0gdXRpbC5iaW5kKHByb2Nlc3NSZXF1ZXN0U3RhdHVzLCB0aGlzKTtcblxuICAgICAgICAgICAgdmFyIG1ldGhvZCA9IG9wdGlvbnMubWV0aG9kLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICB2YXIgZGF0YSA9IHt9O1xuICAgICAgICAgICAgaWYgKG1ldGhvZCA9PT0gJ0dFVCcpIHtcbiAgICAgICAgICAgICAgICB1dGlsLm1peChkYXRhLCBvcHRpb25zLmRhdGEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9wdGlvbnMuY2FjaGUgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgZGF0YVtUSU1FU1RBTVBfUEFSQU1fS0VZXSA9ICtuZXcgRGF0ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHF1ZXJ5ID0gdGhpcy5ob29rcy5zZXJpYWxpemVEYXRhKCcnLCBkYXRhLCAnYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkJyk7XG4gICAgICAgICAgICB2YXIgdXJsID0gb3B0aW9ucy51cmw7XG4gICAgICAgICAgICBpZiAocXVlcnkpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGVsaW1pdGVyID0gdXJsLmluZGV4T2YoJz8nKSA+PSAwID8gJyYnIDogJz8nO1xuICAgICAgICAgICAgICAgIHVybCArPSBkZWxpbWl0ZXIgKyBxdWVyeTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgeGhyLm9wZW4obWV0aG9kLCB1cmwsIHRydWUpO1xuXG4gICAgICAgICAgICBpZiAodHlwZW9mIHRoaXMuaG9va3MuYmVmb3JlU2VuZCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIHRoaXMuaG9va3MuYmVmb3JlU2VuZChmYWtlWEhSLCBvcHRpb25zKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKG1ldGhvZCA9PT0gJ0dFVCcpIHtcbiAgICAgICAgICAgICAgICB4aHIuc2VuZCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIGNvbnRlbnRUeXBlID0gb3B0aW9ucy5jb250ZW50VHlwZSB8fCAnYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkJztcbiAgICAgICAgICAgICAgICB2YXIgcXVlcnkgPSB0aGlzLmhvb2tzLnNlcmlhbGl6ZURhdGEoJycsIG9wdGlvbnMuZGF0YSwgY29udGVudFR5cGUsIGZha2VYSFIpO1xuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLmNoYXJzZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGVudFR5cGUgKz0gJztjaGFyc2V0PScgKyBvcHRpb25zLmNoYXJzZXQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHhoci5zZXRSZXF1ZXN0SGVhZGVyKCdDb250ZW50LVR5cGUnLCBjb250ZW50VHlwZSk7XG4gICAgICAgICAgICAgICAgeGhyLnNlbmQocXVlcnkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAob3B0aW9ucy50aW1lb3V0ID4gMCkge1xuICAgICAgICAgICAgICAgIHZhciBub3RpZnlUaW1lb3V0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAgICAgICAgICogQGV2ZW50IHRpbWVvdXRcbiAgICAgICAgICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAgICAgICAgICog5Lu75oSP5LiA5Liq6K+35rGC5oiQ5Yqf5pe26Kem5Y+R77yMXG4gICAgICAgICAgICAgICAgICAgICAqIOWcqOatpOS6i+S7tuWQjuS8muWGjeinpuWPkeS4gOasoXtAbGluayBBamF4I2ZhaWx95LqL5Lu2XG4gICAgICAgICAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgICAgICAgICAqIEBwYXJhbSB7bWV0YS5GYWtlWEhSfSB4aHIg6K+35rGC5a+56LGhXG4gICAgICAgICAgICAgICAgICAgICAqIEBwYXJhbSB7bWV0YS5BamF4T3B0aW9ufSBvcHRpb25zIOivt+axgueahOmFjee9ruS/oeaBr1xuICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5maXJlKFxuICAgICAgICAgICAgICAgICAgICAgICAgJ3RpbWVvdXQnLFxuICAgICAgICAgICAgICAgICAgICAgICAgeyB4aHI6IGZha2VYSFIsIG9wdGlvbnM6IG9wdGlvbnMgfVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICBmYWtlWEhSLnN0YXR1cyA9IDQwODsgLy8gSFRUUCA0MDg6IFJlcXVlc3QgVGltZW91dFxuICAgICAgICAgICAgICAgICAgICBmYWtlWEhSLmFib3J0KCk7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB2YXIgdGljayA9IHNldFRpbWVvdXQodXRpbC5iaW5kKG5vdGlmeVRpbWVvdXQsIHRoaXMpLCBvcHRpb25zLnRpbWVvdXQpO1xuICAgICAgICAgICAgICAgIGZha2VYSFIuZW5zdXJlKGZ1bmN0aW9uICgpIHsgY2xlYXJUaW1lb3V0KHRpY2spOyB9KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIGZha2VYSFI7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIOWPkei1t+S4gOS4qmBHRVRg6K+35rGCXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSB1cmwg6K+35rGC55qE5Zyw5Z2AXG4gICAgICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbZGF0YV0g6K+35rGC55qE5pWw5o2uXG4gICAgICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2NhY2hlXSDlhrPlrprmmK/lkKblhYHorrjnvJPlrZhcbiAgICAgICAgICogQHJldHVybiB7bWV0YS5GYWtlWEhSfVxuICAgICAgICAgKi9cbiAgICAgICAgZXhwb3J0cy5nZXQgPSBmdW5jdGlvbiAodXJsLCBkYXRhLCBjYWNoZSkge1xuICAgICAgICAgICAgdmFyIG9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgbWV0aG9kOiAnR0VUJyxcbiAgICAgICAgICAgICAgICB1cmw6IHVybCxcbiAgICAgICAgICAgICAgICBkYXRhOiBkYXRhLFxuICAgICAgICAgICAgICAgIGNhY2hlOiBjYWNoZSB8fCB0aGlzLmNvbmZpZy5jYWNoZVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJlcXVlc3Qob3B0aW9ucyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIOWPkei1t+S4gOS4qmBHRVRg6K+35rGC5bm26I635Y+WSlNPTuaVsOaNrlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ30gdXJsIOivt+axgueahOWcsOWdgFxuICAgICAgICAgKiBAcGFyYW0ge09iamVjdH0gW2RhdGFdIOivt+axgueahOaVsOaNrlxuICAgICAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtjYWNoZV0g5Yaz5a6a5piv5ZCm5YWB6K6457yT5a2YXG4gICAgICAgICAqIEByZXR1cm4ge21ldGEuRmFrZVhIUn1cbiAgICAgICAgICovXG4gICAgICAgIGV4cG9ydHMuZ2V0SlNPTiA9IGZ1bmN0aW9uICh1cmwsIGRhdGEsIGNhY2hlKSB7XG4gICAgICAgICAgICB2YXIgb3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICBtZXRob2Q6ICdHRVQnLFxuICAgICAgICAgICAgICAgIHVybDogdXJsLFxuICAgICAgICAgICAgICAgIGRhdGE6IGRhdGEsXG4gICAgICAgICAgICAgICAgZGF0YVR5cGU6ICdqc29uJyxcbiAgICAgICAgICAgICAgICBjYWNoZTogY2FjaGUgfHwgdGhpcy5jb25maWcuY2FjaGVcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yZXF1ZXN0KG9wdGlvbnMpO1xuICAgICAgICB9O1xuXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIOWPkei1t+S4gOS4qmBQT1NUYOivt+axglxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ30gdXJsIOivt+axgueahOWcsOWdgFxuICAgICAgICAgKiBAcGFyYW0ge09iamVjdH0gW2RhdGFdIOivt+axgueahOaVsOaNrlxuICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ30gW2RhdGFUeXBlPVwianNvblwiXSDmjIflrprlk43lupTnmoTmlbDmja7moLzlvI9cbiAgICAgICAgICogQHJldHVybiB7bWV0YS5GYWtlWEhSfVxuICAgICAgICAgKi9cbiAgICAgICAgZXhwb3J0cy5wb3N0ID0gZnVuY3Rpb24gKHVybCwgZGF0YSwgZGF0YVR5cGUpIHtcbiAgICAgICAgICAgIHZhciBvcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgICAgICAgIHVybDogdXJsLFxuICAgICAgICAgICAgICAgIGRhdGE6IGRhdGEsXG4gICAgICAgICAgICAgICAgZGF0YVR5cGU6IGRhdGFUeXBlIHx8ICdqc29uJ1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJlcXVlc3Qob3B0aW9ucyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIOWPkemAgeS4gOS4quaXpeW/l+ivt+axgu+8jOivpeivt+axguWPqui0n+i0o+WPkeWHuu+8jOS4jei0n+i0o+S/neivgemAgei+vu+8jOS4lOS4jeaUr+aMgeWbnuiwg+WHveaVsFxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ30gdXJsIOWPkemAgeeahOebruagh1VSTFxuICAgICAgICAgKiBAcGFyYW0ge09iamVjdH0gW2RhdGFdIOmineWklua3u+WKoOeahOWPguaVsFxuICAgICAgICAgKi9cbiAgICAgICAgZXhwb3J0cy5sb2cgPSBmdW5jdGlvbiAodXJsLCBkYXRhKSB7XG4gICAgICAgICAgICB2YXIgaW1nID0gbmV3IEltYWdlKCk7XG4gICAgICAgICAgICB2YXIgcG9vbCA9IHdpbmRvdy5FUl9MT0dfUE9PTCB8fCAod2luZG93LkVSX0xPR19QT09MID0ge30pO1xuICAgICAgICAgICAgdmFyIGlkID0gK25ldyBEYXRlKCk7XG4gICAgICAgICAgICBwb29sW2lkXSA9IGltZztcblxuICAgICAgICAgICAgaW1nLm9ubG9hZCA9IGltZy5vbmVycm9yID0gaW1nLm9uYWJvcnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgLy8g5aaC5p6c6L+Z5LiqaW1n5b6I5LiN5bm45q2j5aW95Yqg6L295LqG5LiA5Liq5a2Y5Zyo55qE6LWE5rqQ77yM5Y+I5piv5LiqZ2lm5Yqo55S777yMXG4gICAgICAgICAgICAgICAgLy8g5YiZ5ZyoZ2lm5Yqo55S75pKt5pS+6L+H56iL5Lit77yMaW1n5Lya5aSa5qyh6Kem5Y+Rb25sb2Fk77yM5Zug5q2k5LiA5a6a6KaB5riF56m6XG4gICAgICAgICAgICAgICAgaW1nLm9ubG9hZCA9IGltZy5vbmVycm9yID0gaW1nLm9uYWJvcnQgPSBudWxsO1xuXG4gICAgICAgICAgICAgICAgcG9vbFtpZF0gPSBudWxsO1xuXG4gICAgICAgICAgICAgICAgLy8g5LiL6Z2i6L+Z5Y+l6Z2e5bi46YeN6KaB77yMXG4gICAgICAgICAgICAgICAgLy8gbmV3IEltYWdl5Yib5bu655qE5pivRE9N77yMXG4gICAgICAgICAgICAgICAgLy8gRE9N55qE5LqL5Lu25Lit5b2i5oiQ6Zet5YyF546v5byV55SoRE9N5piv5YW45Z6L55qE5YaF5a2Y5rOE6Zyy77yMXG4gICAgICAgICAgICAgICAgLy8g5Zug5q2k6L+Z6YeM5LiA5a6a6KaB572u5Li6bnVsbFxuICAgICAgICAgICAgICAgIGltZyA9IG51bGw7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB2YXIgcXVlcnkgPSB0aGlzLmhvb2tzLnNlcmlhbGl6ZURhdGEoJycsIGRhdGEsICdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnKTtcbiAgICAgICAgICAgIGlmIChxdWVyeSkge1xuICAgICAgICAgICAgICAgIHZhciBkZWxpbWl0ZXIgPSB1cmwuaW5kZXhPZignPycpID49IDAgPyAnOicgOiAnPyc7XG4gICAgICAgICAgICAgICAgdXJsICs9IGRlbGltaXRlciArIHF1ZXJ5O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8g5LiA5a6a6KaB5Zyo5rOo5YaM5LqG5LqL5Lu25LmL5ZCO5YaN6K6+572uc3Jj77yMXG4gICAgICAgICAgICAvLyDkuI3nhLblpoLmnpzlm77niYfmmK/or7vnvJPlrZjnmoTor53vvIzkvJrplJnov4fkuovku7blpITnkIbvvIxcbiAgICAgICAgICAgIC8vIOacgOWQju+8jOWvueS6jnVybOacgOWlveaYr+a3u+WKoOWuouaIt+err+aXtumXtOadpemYsuatoue8k+WtmO+8jFxuICAgICAgICAgICAgLy8g5ZCM5pe25pyN5Yqh5Zmo5Lmf6YWN5ZCI5LiA5LiL5Lyg6YCSYENhY2hlLUNvbnRyb2w6IG5vLWNhY2hlO2BcbiAgICAgICAgICAgIGltZy5zcmMgPSB1cmw7XG4gICAgICAgIH07XG5cbiAgICAgICAgdmFyIEFqYXggPSByZXF1aXJlKCdlb28nKS5jcmVhdGUocmVxdWlyZSgnZmMtbWluaS1ldmVudC9FdmVudFRhcmdldCcpLCBleHBvcnRzKTtcbiAgICAgICAgdmFyIGluc3RhbmNlID0gbmV3IEFqYXgoKTtcbiAgICAgICAgaW5zdGFuY2UuQWpheCA9IEFqYXg7XG4gICAgICAgIHJldHVybiBpbnN0YW5jZTtcbiAgICB9XG4pO1xuIl19